package com.alibaba.citrus.cr.mn.order.center.forecastorder.impl;

import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.enums.ordercenter.DictionaryTypeEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.InnerMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.lock.SaleRedisLock;
import com.alibaba.citrus.cr.mn.order.center.common.constants.ForecastConstants;
import com.alibaba.citrus.cr.mn.order.center.common.util.AssertUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.TrimUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BaseDataServiceAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BusinessUnitAbilityAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.DictionaryVerifyAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.function.common.SendMsgService;
import com.alibaba.citrus.cr.mn.order.center.facade.repository.ForecastOrderLineQueryRepository;
import com.alibaba.citrus.cr.mn.order.center.facade.repository.ForecastOrderQueryRepository;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.ForecastOrderBizDomainService;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.ability.ForecastOrderAbility;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.ability.ForecastOrderGroupAbility;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.convert.ForecastOrderLineBizQueryRequestToFOLineRepoQueryReqConvertor;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.convert.ForecastOrderLineSDOToForecastOrderLineBizQueryResponseConvertor;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.convert.ForecastOrderSDOToForecastOrderBizQueryResponseConvertor;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.entity.ForecastOrderEntity;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.event.ForecastConfirmEvent;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.event.ForecastCreateEvent;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.factory.ForecastOrderFactory;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.service.ForecastOrderBizQueryService;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.service.ForecastOrderBizWriteService;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.db.service.CustomSequenceAccessor;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.crb2btradecenter.messagetask.model.MessageTask;
import com.epoch.app.crb2btradecenter.messagetask.service.MessageTaskService;
import com.epoch.app.crb2btradecenter.model.dto.MessageTaskLoadListRequest;
import com.epoch.app.crb2btradecenter.model.enums.MessageTaskTypeEnum;
import com.epoch.app.crforecastsales.bo.ForecastOrderBO;
import com.epoch.app.crforecastsales.sdo.ForecastOrderSDO;
import com.epoch.app.mnordercenter.model.dto.*;
import com.epoch.app.mnordercenter.orderbaserequest.OrderLineAtomCreateResponse;
import com.google.common.collect.Lists;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static com.alibaba.citrus.cr.mn.order.center.common.constants.RedisLockConstants.*;

@Service
@Primary
public class ForecastOrderBizDomainServiceImpl implements ForecastOrderBizDomainService {

    private static final Log log = Log.getLogger(ForecastOrderBizDomainServiceImpl.class);

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;
    @Resource
    private CustomSequenceAccessor customSequenceAccessor;
    @Resource
    private ForecastOrderBizWriteService forecastOrderBizWriteService;
    @Resource
    private ForecastOrderBizQueryService forecastOrderBizQueryService;
    @Resource
    private ForecastOrderLineQueryRepository forecastOrderLineQueryRepository;
    @Resource
    private ForecastOrderQueryRepository forecastOrderQueryRepository;
    @Resource
    private BusinessUnitAbilityAdapter businessUnitAbilityAdapter;
    @Resource
    private MessageTaskService messageTaskService;
    @Resource
    private BaseDataServiceAdapter baseDataServiceAdapter;
    @Resource
    private DictionaryVerifyAdapter dictionaryVerifyAdapter;
    @Resource
    private SendMsgService sendMsgService;

    @Override
    @FacadeInvoker
    public Result<ForecastBizAsyncResponse> batchCreate(ForecastOrderBizBatchCreateRequest request) {
        String lockKey = FORECAST_ORDER_BIZ_PREFIX + request.getFromSys() + "#" + request.getReqNo();
        log.info("ForecastOrderBizDomainServiceImpl#batchCreate lockKey={}", lockKey);
        try (SaleRedisLock reqLock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!reqLock.lock()) {
                log.error("ForecastOrderBizDomainServiceImpl#batchCreate 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.createDraft(request);

            // 入参非空和长度校验
            ForecastOrderAbility.createParamsInvalid(forecastOrderEntities);

            String batchTaskId = customSequenceAccessor.getNextStringSequence("cr_b2b_trade_center", "batchCreateOrderSequence");
            // 请求号幂等校验
            String existBatchTaskId = reqIdempotentProcess(batchTaskId, request.getReqNo(), request.getFromSys());

            ForecastBizAsyncResponse createResponse = new ForecastBizAsyncResponse();
            if (StringUtils.isNotBlank(existBatchTaskId)) {
                // 幂等校验未通过，直接返回原请求的批次号
                createResponse.setBatchTaskId(existBatchTaskId);
                return Result.success(createResponse);
            }

            List<ForecastOrderBO> createForecastOrderBOS = forecastOrderEntities.stream()
                    .map(ForecastOrderEntity::getForecastOrderBO)
                    .collect(Collectors.toList());
            log.info("createForecastOrderBOS参数:{}",JSON.toJSONString(createForecastOrderBOS));
            // 构造异步创建消息对象
            ForecastCreateEventRequest forecastCreateEventRequest = new ForecastCreateEventRequest();
            forecastCreateEventRequest.setCreateForecastOrderBOS(createForecastOrderBOS);
            forecastCreateEventRequest.setTaskId(batchTaskId);
            forecastCreateEventRequest.setBusinessUnitCode(request.getBusinessUnitCode());
            forecastCreateEventRequest.setFromSys(request.getFromSys());
            ForecastCreateEvent forecastEvent = new ForecastCreateEvent(forecastCreateEventRequest);
            applicationEventPublisher.publishEvent(forecastEvent);

            createResponse.setBatchTaskId(batchTaskId);
            return Result.success(createResponse);
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchCreate error", e);
            throw e;
        }
    }

    @Override
    @FacadeInvoker
    public Result<ForecastBizSyncResponse> create(ForecastOrderBizCreateRequest request) {
        String lockKey = FORECAST_ORDER_BIZ_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("ForecastOrderBizDomainServiceImpl#create lockKey={}", lockKey);
        try (SaleRedisLock reqLock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!reqLock.lock()) {
                log.error("ForecastOrderBizDomainServiceImpl#create 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }
            ForecastOrderBizBatchCreateRequest forecastOrderBizBatchCreateRequest = new ForecastOrderBizBatchCreateRequest();
            List<CreateForecastDTO> createForecastDTOS = new ArrayList<>();
            createForecastDTOS.add(request.getCreateForecastOrderDTO());
            forecastOrderBizBatchCreateRequest.setReqNo(request.getReqNo());
            forecastOrderBizBatchCreateRequest.setFromSys(request.getFromSys());
            forecastOrderBizBatchCreateRequest.setBusinessUnitCode(request.getBusinessUnitCode());
            forecastOrderBizBatchCreateRequest.setBusinessType(request.getBusinessType());
            forecastOrderBizBatchCreateRequest.setCreateForecastOrderDTOS(createForecastDTOS);
            List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.createDraft(forecastOrderBizBatchCreateRequest);
            // 入参非空和长度校验
            ForecastOrderAbility.createParamsInvalid(forecastOrderEntities);
            List<ForecastOrderBO> createForecastOrderBOS = forecastOrderEntities.stream()
                    .map(ForecastOrderEntity::getForecastOrderBO)
                    .collect(Collectors.toList());

            List<CreateForecastResponseDTO> createForecastResponseDTOS = forecastOrderBizWriteService.batchCreate(createForecastOrderBOS, null, request.getFromSys(), request.getBusinessUnitCode());
            if (CollectionUtils.isEmpty(createForecastResponseDTOS)) {
                return Result.fail("OC-04-001-01-16-002", "预报订单创建失败");
            }

            CreateForecastResponseDTO createForecastResponseDTO = createForecastResponseDTOS.get(0);
            if (!createForecastResponseDTO.getSuccess()) {
                return Result.fail(createForecastResponseDTO.getErrorCode(), createForecastResponseDTO.getMessage());
            }

            ForecastBizSyncResponse forecastBizSyncResponse = new ForecastBizSyncResponse();
            forecastBizSyncResponse.setSalesOrderNo(createForecastResponseDTO.getSalesOrderNo());
            forecastBizSyncResponse.setSourceOrderNo(createForecastResponseDTO.getSourceOrderNo());
            List<OrderLineAtomCreateResponse> orderLineList = new ArrayList<>();
            createForecastResponseDTO.getForecastDetailResponseDTOS().forEach(forecastDetail -> {
                OrderLineAtomCreateResponse orderLine = new OrderLineAtomCreateResponse();
                orderLine.setLineNum(forecastDetail.getLineNum());
                orderLine.setSourceLineNum(forecastDetail.getSourceLineNum());
                orderLineList.add(orderLine);
            });
            forecastBizSyncResponse.setOrderDetails(orderLineList);
            return Result.success(forecastBizSyncResponse);
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#create error", e);
            throw e;
        }
    }

    public String reqIdempotentProcess(String batchTaskId, String reqNo, String fromSys) {
        try {
            // 请求号幂等校验
            MessageTaskLoadListRequest loadRequest = new MessageTaskLoadListRequest();
            loadRequest.setType(MessageTaskTypeEnum.OC_FORECAST_ORDER_BATCH_CREATE.getValue());
            loadRequest.setReqNo(reqNo);
            loadRequest.setFromSys(fromSys);
            Result<List<MessageTask>> result = messageTaskService.loadList(loadRequest);
            log.info("ForecastOrderBizDomainServiceImpl#reqIdempotentProcess loadList result=", JSON.toJSONString(result));

            if (Objects.nonNull(result) && result.getTotal() > 0) {
                return result.getResult().get(0).getBatchNo();
            }

            // 保存任务
            MessageTask messageTask = new MessageTask();
            messageTask.setBatchNo(batchTaskId);
            messageTask.setReqNo(reqNo);
            messageTask.setFromSys(fromSys);
            messageTask.setType(MessageTaskTypeEnum.OC_FORECAST_ORDER_BATCH_CREATE.getValue());
            messageTask.setGmt_create(new Date());
            messageTask.setGmt_modified(new Date());
            messageTask.setStatus(1);
            messageTaskService.create(messageTask);
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#reqIdempotentProcess loadList error", e);
            throw e;
        }
        return "";
    }

    @Override
    @FacadeInvoker
    public Result<List<SubmitForecastResponseDTO>> batchSubmit(ForecastBizBatchSubmitRequest request) {
        StopWatchUtils.start("预报订单批量提交", "submitParamsInvalid");
        try {
            ForecastOrderAbility.submitParamsInvalid(request);
        } catch (FunctionException e) {
            return Result.fail(e.getErrorCode(), e.getErrorMessage());
        }
        StopWatchUtils.stop();

        // 业务单元编码存在性校验
        StopWatchUtils.start("预报订单批量提交", "checkBusinessUnitCode");
        Boolean isExist = businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode());
        StopWatchUtils.stop();
        if (!isExist) {
            throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
        }

        return forecastOrderBizWriteService.batchSubmit(request);
    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastOrderBizQueryAnalysisResponse>> queryAnalysis(ForecastOrderBizQueryAnalysisRequest request) {
        try {
            ForecastOrderAbility.queryAnalysisCheck(request);
            // 业务单元编码存在性校验
            if (!businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode())) {
                throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
            }
            return forecastOrderBizQueryService.queryAnalysis(request);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#queryAnalysis error", e);
            log.error("ForecastOrderBizDomainServiceImpl#queryAnalysis error2:{}", JSON.toJSONString(e));
            Result result =Result.fail(e.getErrorCode(), e.getMessage());
            log.error("ForecastOrderBizDomainServiceImpl#queryAnalysis result:{}", JSON.toJSONString(result));
            throw e;
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#queryAnalysis error", e);
            return Result.fail("OC-00-000-01-99-001", e.getMessage());
        }
    }

    @Override
    @FacadeInvoker
    public Result<QueryForecastResponse> query(QueryForecastRequest request) {
        if (StringUtils.isBlank(request.getSalesOrderNo()) && StringUtils.isBlank(request.getSourceOrderNo())) {
            throw new FunctionException("OC-01-001-01-15-010", "预报订单单号、来源单号");
        }
        AssertUtils.isTrue(StringUtils.isBlank(request.getBusinessType()), "OC-01-001-01-15-001", "业态编码");
//        AssertUtils.isTrue(StringUtils.isBlank(request.getBusinessUnitCode()), "OC-01-001-01-15-001", "业务单元编码");
        AssertUtils.lengthCheck(request.getBusinessUnitCode(), 50, false, "OC-01-001-01-15-004", "业务单元编码");
        AssertUtils.lengthCheck(request.getBusinessType(), 10, true, "OC-01-001-01-15-004", "业态编码");
        AssertUtils.lengthCheck(request.getFromSys(), 50, false, "OC-01-001-01-15-004", "来源系统编码");

        AssertUtils.lengthCheck(request.getSalesOrderNo(), 50, false, "OC-01-001-01-15-004", "预报订单单号");
        AssertUtils.lengthCheck(request.getSourceOrderNo(), 50, false, "OC-01-001-01-15-004", "来源单号");

        dictionaryVerifyAdapter.verifyDictionary(DictionaryTypeEnum.BUSINESS_TYPE.getCode(), request.getBusinessType(), new FunctionException("OC-01-001-01-15-006", "业态编码"));
        if (StringUtils.isNotBlank(request.getFromSys())) {
            dictionaryVerifyAdapter.verifyDictionary(DictionaryTypeEnum.FROM_SYS.getCode(), request.getFromSys(), new FunctionException("OC-01-001-01-15-006", "来源系统编码"));
        }
        if (StringUtils.isNotBlank(request.getBusinessUnitCode())) {
            // 合法性校验
            Boolean isExist = businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode());
            StopWatchUtils.stop();
            if (!isExist) {
                throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
            }
        }
        QueryForecastResponse response = forecastOrderBizQueryService.query(request);
        Result<QueryForecastResponse> result = Result.success(response);
        if (Objects.nonNull(response)) {
            result.setTotal(1);
        }
        return result;
    }

    @Override
    @FacadeInvoker
    public Result<List<CancelForecastResponseDTO>> batchCancel(CancelForecastRequest request) {
        StopWatchUtils.start("预报订单批量取消", "cancelRequestCheck");
        ForecastOrderAbility.cancelRequestCheck(request);
        StopWatchUtils.stop();

        return forecastOrderBizWriteService.batchCancel(request);
    }

    @Override
    @FacadeInvoker
    public Result<List<PageQueryForecastDetailResponse>> pageQueryLine(PageQueryForecastLineRequest request) {
        return pageQueryLine(request, null);
    }

    @Override
    @FacadeInvoker
    public Result<List<PageQueryForecastDetailResponse>> pageQueryLine(PageQueryForecastLineRequest request, String orderCategory) {
        TrimUtils.removeSpace(request);
        if (OrderCategoryEnum.GROUP.getCode().equals(orderCategory) || OrderCategoryEnum.COMPANY.getCode().equals(orderCategory)) {
            ForecastOrderGroupAbility.pageQueryLineRequestCheck(request, orderCategory);
        } else {
            ForecastOrderAbility.pageQueryLineRequestCheck(request);
        }
        return forecastOrderBizQueryService.pageQueryLine(request, orderCategory);
    }

    @Override
    public Result<List<QueryForecastResponse>> pageQuery(PageQueryForecastRequest request) {
        return pageQuery(request, null);
    }

    @Override
    @FacadeInvoker
    public Result<List<QueryForecastResponse>> pageQuery(PageQueryForecastRequest request, String orderCategory) {
        TrimUtils.removeSpace(request);
        if (OrderCategoryEnum.GROUP.getCode().equals(orderCategory) || OrderCategoryEnum.COMPANY.getCode().equals(orderCategory)) {
            ForecastOrderGroupAbility.pageQueryRequestCheck(request,orderCategory);
        } else {
            ForecastOrderAbility.pageQueryRequestCheck(request);
        }
        return forecastOrderBizQueryService.pageQuery(request, orderCategory);
    }

    @Override
    @FacadeInvoker
    public Result<AnalysisForecastResponseDTO> batchAnalysis(AnalysisForecastRequest request) {
        try {
            ForecastOrderAbility.analysisParamsInvalid(request);
            // 业务单元编码存在性校验
            if (!businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode())) {
                throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
            }
//            ForecastOrderAbility.idempotentProcess(request);@todo 考虑数据存在性校验
            return forecastOrderBizWriteService.batchAnalysis(request);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#pageQuery error", e);
            throw e;
            //return Result.fail(e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#pageQuery error", e);
            return Result.fail("OC-00-000-01-99-001", e.getMessage());
        }
    }

    @Override
    @FacadeInvoker
    public Result<ModifyForecastResponseDTO> modify(ModifyForecastRequest request) {
        try {
            StopWatchUtils.start("预报订单修改", "modifyParamsInvalid");
            ForecastOrderAbility.modifyParamsInvalid(request);
            StopWatchUtils.stop();

            StopWatchUtils.start("预报订单修改", "createModifyEntity");
            ForecastOrderEntity modifyEntity = ForecastOrderFactory.createModifyEntity(request);
            StopWatchUtils.stop();

            // 业务单元编码存在性校验
            if (!businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode())) {
                throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
            }

            //枚举有效性校验
            StopWatchUtils.start("预报订单修改", "modifyParamsEnumDictCheck");
            ForecastOrderAbility.modifyParamsEnumDictCheck(modifyEntity.getForecastOrderBO());
            StopWatchUtils.stop();

            Result<ModifyForecastResponseDTO> result = forecastOrderBizWriteService.modify(modifyEntity);
            // 发送MQ消息通知其他中心
            if (result.isSuccess()) {
                sendMsgService.sendForecastOrderChangeMsg(Lists.newArrayList(result.getResult().getForecastOrderBizNo()), InnerMessageEventEnum.FORECAST_ORDER_UPDATED);
            }
            return result;
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#modify error", e);
            return Result.fail(e.getErrorCode(), e.getErrorMessage());
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#modify error", e);
            return Result.fail("OC-00-000-01-99-001", e.getMessage());
        }
    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastOrderBizQueryActivityResponse>> batchQueryActivity(ForecastOrderBizBatchQueryActivityRequest request) {
        try {
            StopWatchUtils.start("预报订单批量查询活动", "queryActivityRequestCheck");
            ForecastOrderAbility.queryActivityRequestCheck(request);
            StopWatchUtils.stop();
            // 业务单元编码存在性校验
            if (!businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode())) {
                throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
            }
            return forecastOrderBizQueryService.batchQueryActivity(request);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchQueryActivity error", e);
            return Result.fail(e.getErrorCode(), e.getErrorMessage());
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchQueryActivity error", e);
            return Result.fail("OC-00-000-01-99-001", e.getMessage());
        }
    }

    @Override
    @FacadeInvoker
    public Result<ForecastBizAsyncResponse> batchConfirm(ConfirmReplyRequest confirmReplyRequest) {
        log.info("ForecastOrderBizDomainServiceImpl#batchConfirm confirmReplyRequest:{}", JSON.toJSONString(confirmReplyRequest));
        try {
            ForecastBizAsyncResponse responseDTO = new ForecastBizAsyncResponse();
            ForecastOrderAbility.confirmParamsInvalid(confirmReplyRequest);
            //        ForecastOrderAbility.idempotentProcess(request);
            String sequenceNo = customSequenceAccessor.getNextStringSequence("cr_forecast_sales", "sequenceNo");
            confirmReplyRequest.setTaskId(sequenceNo);
            ForecastConfirmEvent forecastEvent = new ForecastConfirmEvent(confirmReplyRequest);
            applicationEventPublisher.publishEvent(forecastEvent);
            responseDTO.setBatchTaskId(sequenceNo);

            return Result.success(responseDTO);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchConfirm error", e);
            throw e;
            //return Result.fail(e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchConfirm error", e);
            return Result.fail("OC-00-000-01-99-001", e.getMessage());
        }
    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastBizGroupResponse>> batchGroupConfirm(ConfirmGroupReplyRequest request) {

        log.info("ForecastOrderBizDomainServiceImpl#batchGroupConfirm request={}", JSON.toJSONString(request));
        String lockKey = FORECAST_ORDER_GROUP_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("ForecastOrderBizDomainServiceImpl#batchGroupConfirm lockKey={}", lockKey);

        try (SaleRedisLock reqLock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!reqLock.lock()) {
                log.error("ForecastOrderBizDomainServiceImpl#batchGroupConfirm 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            List<ForecastBizGroupResponse> forecastBizGroupResponseList = new ArrayList<>();
            ForecastOrderAbility.confirmGroupParamsInvalid(request);
            List<ConfirmReplyResponseDTO> confirmReplyResponseDTOS = forecastOrderBizWriteService.batchGroupConfirm(request);
            for (ConfirmReplyResponseDTO confirmReplyResponseDTO : confirmReplyResponseDTOS) {
                ForecastBizGroupResponse forecastBizGroupResponse = new ForecastBizGroupResponse();
                BeanUtils.copyProperties(confirmReplyResponseDTO, forecastBizGroupResponse);
                forecastBizGroupResponse.setLineNum(confirmReplyResponseDTO.getLineNo());
                forecastBizGroupResponseList.add(forecastBizGroupResponse);
            }
            log.info("forecastBizGroupResponseList结果:{}", JSON.toJSONString(forecastBizGroupResponseList));
            return Result.success(forecastBizGroupResponseList);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchGroupConfirm error", e);
            throw e;
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchGroupConfirm error", e);
            return Result.fail("OC-04-005-01-16-001", "预报订单批量确认失败");
        }
    }

    @Override
    public Result<List<ForecastOrderLineBizQueryResponse>> pageQueryOrderLineList(ForecastOrderLineBizQueryRequest request) {
        try {
            ForecastOrderLineRepoQueryReq forecastOrderLineRepoQueryReq = ForecastOrderLineBizQueryRequestToFOLineRepoQueryReqConvertor.convert(request);
            Result<List<ForecastOrderLineSDO>> response = forecastOrderLineQueryRepository.pageQueryFromEs(forecastOrderLineRepoQueryReq);
            List<ForecastOrderLineBizQueryResponse> result = response.getResult().stream()
                    .map(ForecastOrderLineSDOToForecastOrderLineBizQueryResponseConvertor::convert)
                    .collect(Collectors.toList());

            List<DictionaryResponse> allRefuseReason = baseDataServiceAdapter.queryDictionarys(ForecastConstants.DICT_REFUSE_REASON);
            List<DictionaryResponse> allOrderReason = baseDataServiceAdapter.queryDictionarys(ForecastConstants.DICT_ORDER_REASON);
            List<DictionaryResponse> allShipMethod = baseDataServiceAdapter.queryDictionarys(ForecastConstants.DICT_SHIP_METHOD);
            //List<DictionaryResponse> allForecastTag =  baseDataServiceAdapter.queryDictionarys(ForecastConstants.DICT_FORECAST_TAG);

            List<String> creatorIds = Nullable.stream(result).filter(x -> StringUtils.isNotBlank(x.getCreatorId()) && StringUtils.isBlank(x.getCreatorWorkId())).map(x -> {
                if (x.getCreatorId().startsWith("CZ_")) {
                    //截取CZ_前缀
                    String creatorId = x.getCreatorId().substring(3);
                    return creatorId;
                }
                return x.getCreatorId();
            }).collect(Collectors.toList());
            List<String> updatorIds = Nullable.stream(result).filter(x -> StringUtils.isNotBlank(x.getUpdatorId()) && StringUtils.isBlank(x.getUpdatorWorkId())).map(x -> {
                if (x.getUpdatorId().startsWith("CZ_")) {
                    //截取CZ_前缀
                    String updatorId = x.getUpdatorId().substring(3);
                    return updatorId;
                }
                return x.getUpdatorId();
            }).collect(Collectors.toList());
            creatorIds.addAll(updatorIds);
            Map<String, Modifiers> employeeMap = baseDataServiceAdapter.queryEmployeeMap(creatorIds);

            List<String> bisUnitIds = Nullable.stream(result).filter(x->StringUtils.isNotBlank(x.getBisUnitCode()) && StringUtils.isBlank(x.getBisUnitName())).map(x->x.getBisUnitCode()).collect(Collectors.toList());
            Map<String, OrganizationSDO> organizationMap = baseDataServiceAdapter.baselineGetOrganizationByIds(bisUnitIds);

            for (ForecastOrderLineBizQueryResponse orderResponse : result) {
                BigDecimal hundred = new BigDecimal(100);
                if (StringUtils.isNotBlank(orderResponse.getUnitPrice())) {
                    orderResponse.setUnitPrice(new BigDecimal(orderResponse.getUnitPrice()).divide(hundred, 2, RoundingMode.UP).toString());
                }
                if (StringUtils.isNotBlank(orderResponse.getTotalFee())) {
                    orderResponse.setTotalFee(new BigDecimal(orderResponse.getTotalFee()).divide(hundred, 2, RoundingMode.UP).toString());
                }
                if (StringUtils.isNotBlank(orderResponse.getActivityPrice())) {
                    orderResponse.setActivityPrice(new BigDecimal(orderResponse.getActivityPrice()).divide(hundred, 2, RoundingMode.UP).toString());
                }
                if (StringUtils.isNotBlank(orderResponse.getActivityTotalAmount())) {
                    orderResponse.setActivityTotalAmount(new BigDecimal(orderResponse.getActivityTotalAmount()).divide(hundred, 2, RoundingMode.UP).toString());
                }

                String creatorId = orderResponse.getCreatorId();
                if (StringUtils.isNotBlank(creatorId) && creatorId.startsWith("CZ_")){
                    creatorId = creatorId.substring(3);
                }
                if(StringUtils.isNotBlank(creatorId) && employeeMap.get(creatorId)!=null){
                    orderResponse.setCreatorWorkId(employeeMap.get(creatorId).getWorkId());
                }
                String updatorId = orderResponse.getUpdatorId();
                if (StringUtils.isNotBlank(updatorId) && updatorId.startsWith("CZ_")){
                    updatorId = updatorId.substring(3);
                }
                if(StringUtils.isNotBlank(updatorId) && employeeMap.get(updatorId)!=null){
                    orderResponse.setUpdatorWorkId(employeeMap.get(updatorId).getWorkId());
                }

                if (StringUtils.isNotBlank(orderResponse.getBisUnitCode()) && StringUtils.isBlank(orderResponse.getBisUnitName())) {
                    if(organizationMap.get(orderResponse.getBisUnitCode()) != null){
                        orderResponse.setBisUnitName(organizationMap.get(orderResponse.getBisUnitCode()).getName());
                    }
                }

                if (StringUtils.isNotBlank(orderResponse.getRefuseReasonCode()) && StringUtils.isBlank(orderResponse.getRefuseReasonName())) {
                    allRefuseReason.stream().forEach(x -> {
                        if (x.getCode().equals(orderResponse.getRefuseReasonCode())) {
                            orderResponse.setRefuseReasonName(x.getName());
                            return;
                        }
                    });
                }

                if (StringUtils.isNotBlank(orderResponse.getCreateReasonCode()) && StringUtils.isBlank(orderResponse.getCreateReasonName())) {
                    allOrderReason.stream().forEach(x -> {
                        if (x.getCode().equals(orderResponse.getCreateReasonCode())) {
                            orderResponse.setCreateReasonName(x.getName());
                            return;
                        }
                    });
                }

                if (StringUtils.isNotBlank(orderResponse.getDeliveryMethod()) && StringUtils.isBlank(orderResponse.getDeliveryMethodName())) {
                    allShipMethod.stream().forEach(x -> {
                        if (x.getCode().equals(orderResponse.getDeliveryMethod())) {
                            orderResponse.setDeliveryMethodName(x.getName());
                            return;
                        }
                    });
                }

            }

            return Result.listSuccess(result, response.getTotal());
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#pageQueryOrderLineList error", e);
            throw new FacadeException("OC-01-001-01-16-057");
        }
    }

    @Override
    public Result<ForecastOrderBizQueryResponse> queryForecastOrderDetail(String id) {
        ForecastOrderSDO forecastOrderSDO = forecastOrderQueryRepository.queryDetail(id);
        return Result.success(ForecastOrderSDOToForecastOrderBizQueryResponseConvertor.convert(forecastOrderSDO));
    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastReplyBizModifyResponse>> batchModifyReply(ForecastReplyBizBatchModifyRequest request) {
        try {
            StopWatchUtils.start("预报订单回复批量修改", "replyModifyRequestCheck");
            ForecastOrderAbility.replyModifyRequestCheck(request);
            StopWatchUtils.stop();

            // 业务单元编码存在性校验
            if (!businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode())) {
                throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
            }
            return forecastOrderBizWriteService.batchModifyReply(request);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchModifyReply error", e);
            throw e;
            //return Result.fail(e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchModifyReply error", e);
            return Result.fail("OC-00-000-01-99-001", e.getMessage());
        }
    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastOrderBizCloseResponse>> batchClose(ForecastOrderBizBatchCloseRequest request) {
        ForecastOrderAbility.closeRequestCheck(request);
        // 业务单元编码存在性校验
        if (!businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode())) {
            throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
        }
        return forecastOrderBizWriteService.batchClose(request);
    }

    @Override
    public Result<List<ForecastOrderBizModifyActivityResponse>> batchModifyActivity(ForecastOrderBizBatchModifyActivityRequest request) {
        try {
            ForecastOrderAbility.modifyActivityRequestCheck(request);
            // 业务单元编码存在性校验
            if (!businessUnitAbilityAdapter.checkBusinessUnitCode(request.getBusinessUnitCode())) {
                throw new FunctionException("OC-01-001-01-16-011", request.getBusinessUnitCode());
            }
            return forecastOrderBizWriteService.batchModifyActivity(request);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchModifyActivity error", e);
            return Result.fail(e.getErrorCode(), e.getErrorMessage());
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#batchModifyActivity error", e);
            return Result.fail("OC-00-000-01-99-001", e.getMessage());
        }
    }

    /**
     * F2B批量确认
     *
     * @param request
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<List<ForecastBizGroupResponse>> syncBatchConfirm(ConfirmReplyFulfillRequest request) {
        log.info("ForecastOrderBizDomainServiceImpl#syncBatchConfirm request={}", JSON.toJSONString(request));
        String lockKey = FORECAST_ORDER_GROUP_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("ForecastOrderBizDomainServiceImpl#syncBatchConfirm lockKey={}", lockKey);

        try (SaleRedisLock reqLock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!reqLock.lock()) {
                log.error("ForecastOrderBizDomainServiceImpl#syncBatchConfirm 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            List<ForecastBizGroupResponse> forecastBizGroupResponseList = new ArrayList<>();
            ForecastOrderAbility.confirmSyncGroupParamsInvalid(request);
//            ConfirmReplyRequest confirmReplyRequest = new ConfirmReplyRequest();
//            BeanUtils.copyProperties(request, confirmReplyRequest);
            String sequenceNo = customSequenceAccessor.getNextStringSequence("cr_forecast_sales", "sequenceNo");
            request.setTaskId(sequenceNo);
            List<ConfirmReplyResponseDTO> confirmReplyResponseDTOS = forecastOrderBizWriteService.syncBatchConfirmWith(request);
            for (ConfirmReplyResponseDTO confirmReplyResponseDTO : confirmReplyResponseDTOS) {
                ForecastBizGroupResponse forecastBizGroupResponse = new ForecastBizGroupResponse();
                BeanUtils.copyProperties(confirmReplyResponseDTO, forecastBizGroupResponse);
                forecastBizGroupResponse.setLineNum(confirmReplyResponseDTO.getLineNo());
                forecastBizGroupResponseList.add(forecastBizGroupResponse);
            }
            log.info("forecastBizGroupResponseList结果:{}", JSON.toJSONString(forecastBizGroupResponseList));
            return Result.success(forecastBizGroupResponseList);
        } catch (FunctionException e) {
            log.error("ForecastOrderBizDomainServiceImpl#syncBatchConfirm error", e);
            throw e;
        } catch (Exception e) {
            log.error("ForecastOrderBizDomainServiceImpl#syncBatchConfirm error", e);
            return Result.fail("OC-04-005-01-16-001", "预报订单批量确认失败");
        }
    }
}
